package com.ydj.framework.task;

import com.ydj.AppEnvironment;
import com.ydj.framework.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.util.Date;

@Slf4j
@ConditionalOnExpression("${job.enable}==true")
public abstract class BaseJob implements SchedulingConfigurer {
    /**
     * 一个编码用于定时器运行时的次数分割
     */
    private String code;

    @Value("${job.log}")
    private Boolean logEnable;
    @Autowired
    private AppEnvironment appEnvironment;

    public abstract String cronExpress();

    protected abstract void doExecuteInternal() throws Exception;

    protected abstract String name();

    protected Boolean logEnable() {
        return logEnable;
    }

    // 只能在主服务器上运行
    protected abstract boolean onlyRunAtMasterServer();

    public void jobLogInfo(String msg) {
        if (logEnable()) {
            log.info("【定时器】【{}】[{}] {}", name(), code, msg);
        }
    }

    public void jobLogError(String msg) {
        if (logEnable()) {
            log.error("【定时器】【{}】[{}] {}", name(), code, msg);
        }
    }

    public void jobLogError(String msg, Throwable e) {
        if (logEnable()) {
            log.error("【定时器】【{}】[{}] {}", name(), code, msg, e);
        }
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setThreadNamePrefix("JobTask");
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler);

        scheduledTaskRegistrar.addTriggerTask(() -> {
            code = CommonUtils.getRandomCode(4);
            code = code.substring(code.length() - 4);
            jobLogInfo("开始运行");
            try {
                if (!onlyRunAtMasterServer() || (onlyRunAtMasterServer() && appEnvironment.isMaster())) {
                    doExecuteInternal();
                } else {
                    jobLogInfo("该任务只在主服务器上运行，放弃");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            jobLogInfo("结束运行");
        }, triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(cronExpress());
            Date nextExecDate = cronTrigger.nextExecutionTime(triggerContext);
            return nextExecDate;
        });
    }
}